#!/bin/bash

# 功能：基于 pass 和 nodes 文件实现多主机免密登录和远程命令执行


# 自定义SSH端口配置（默认22，可通过环境变量覆盖）
SSH_PORT="22"

# 定义通用SSH与SCP参数
SSH_OPTS="-p $SSH_PORT -o StrictHostKeyChecking=no -o ServerAliveInterval=15 -o ConnectTimeout=30"
SCP_OPTS="-P $SSH_PORT -o StrictHostKeyChecking=no"

# 定义文件路径
# PASS_FILE="./config/pass"
NODES_FILE="./config/nodes"
SSHPASS_FILE="./main/sshpass-1.06-2.el7.x86_64.rpm"
SSH_KEY_PATH="$HOME/.ssh/id_rsa"
SCRIPT_TO_SCP="./bin/generate_ssh_key.sh" 

# --------------------- 函数定义 ---------------------
# 检查文件是否存在
check_file() {
  if [ ! -f "$1" ]; then
    echo "错误：文件 $1 不存在！"
    exit 1
  fi
}

# 读取用户名和密码
read_credentials() {
  read -r IP NODE_ID USERNAME PASSWORD < "$NODES_FILE"
  if [ -z "$IP" ] || [ -z "$NODE_ID" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
    echo "错误：nodes 文件格式不正确！"
    exit 1
  fi
}

# 生成 SSH 密钥对
generate_ssh_key() {
  if [ ! -f "$SSH_KEY_PATH" ]; then
    echo "生成 SSH 密钥对..."
    ssh-keygen -t rsa -b 4096 -f "$SSH_KEY_PATH" -N ""
  fi
}


# 安装 sshpass
install_sshpass() {
  if ! command -v sshpass &> /dev/null; then
    echo "安装 sshpass..."
    sudo rpm -ivh "$SSHPASS_FILE"
  fi
}


# 分发公钥到指定主机
copy_ssh_key() {
  local IP=$1
  local USERNAME=$2
  local PASSWORD=$3
  echo "处理主机: $IP"
    sshpass -p "$PASSWORD" ssh-copy-id -i "$SSH_KEY_PATH.pub" -o StrictHostKeyChecking=no -o "Port=$SSH_PORT" "$USERNAME@$IP"
  if [ $? -eq 0 ]; then
    echo "公钥发送成功: $IP"
    return 0
  else
    echo "公钥发送失败: $IP"
    return 1
  fi
}


# 通过 SCP 将脚本发送到目标主机并执行

send_and_execute_script() {
  local IP=$1
  local USERNAME=$2
  local PASSWORD=$3
  echo "将脚本发送到主机: $IP"
  
  # 发送脚本和文件，任一失败则返回错误
  if [ "$SSH_PORT" != "22" ]; then
    sed -i "s/^SSH_PORT=\"22\"/SSH_PORT=\"$SSH_PORT\"/" "$SCRIPT_TO_SCP"
  fi
  sshpass -p "$PASSWORD" scp -P "$SSH_PORT" "$SCRIPT_TO_SCP"  "$USERNAME@$IP:/tmp/generate_ssh_key.sh"
  if [ $? -eq 0 ]; then
    echo "generate_ssh_key.sh"传输完成
  fi
  sshpass -p "$PASSWORD" scp -P "$SSH_PORT" $SCP_OPTS "$NODES_FILE" "$USERNAME@$IP:/tmp/nodes"
  if [ $? -eq 0 ]; then
    echo "nodes"传输完成
  fi
  sshpass -p "$PASSWORD" scp -P "$SSH_PORT" $SCP_OPTS "$SSHPASS_FILE" "$USERNAME@$IP:/tmp/sshpass-1.06-2.el7.x86_64.rpm"
  if [ $? -eq 0 ]; then
    echo "sshpass"传输完成
  fi
  # 执行远程脚本并检查状态
  if ! sshpass -p "$PASSWORD" ssh $SSH_OPTS "$USERNAME@$IP" "/usr/bin/chmod +x /tmp/generate_ssh_key.sh"; then
    echo "$IP主机 脚本添加权限失败"
    return 1
  fi

  if ! sshpass -p "$PASSWORD" ssh $SSH_OPTS "$USERNAME@$IP" "bash /tmp/generate_ssh_key.sh"; then
    echo "$IP 脚本执行失败"
    return 1
  fi
  # wait
  #echo "$IP 远程脚本执行完毕"
  return 0
}


# --------------------- 主流程 ---------------------
# 检查文件（必要的前置检查，若失败则退出）
check_file "$NODES_FILE"

# 读取凭据
read_credentials

# 初始化环境
generate_ssh_key
install_sshpass



# 读取文件中的每一行，获取 IP 地址并进行操作
for IP in $(awk '{print $1}' "$NODES_FILE"); do
  # 提取 IP 和 NODE_ID
  NODE_ID=$(awk -v ip="$IP" '$1 == ip {print $2}' "$NODES_FILE")
  USERNAME=$(awk -v ip="$IP" '$1 == ip {print $3}' "$NODES_FILE")
  PASSWORD=$(awk -v ip="$IP" '$1 == ip {print $4}' "$NODES_FILE")

  echo "========================================="
  echo "处理节点：IP = '$IP', NODE_ID = '$NODE_ID'"

  # 跳过空行或格式错误
  if [ -z "$IP" ] || [ -z "$NODE_ID" ]; then
    echo "警告：行内容格式错误，跳过"
    continue
  fi

  # 分发公钥，若失败则记录并跳过
  if ! copy_ssh_key "$IP" "$USERNAME" "$PASSWORD"; then
    echo "错误：无法分发公钥到 $IP，跳过该节点"
    continue
  fi

  # 将脚本发送到对端机器并执行生成 SSH 密钥
  send_and_execute_script "$IP" "$USERNAME" "$PASSWORD"
done

echo "所有操作已完成！"